package com.example.bounce;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ConfigurationInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import com.example.glsurfaceview.MyGLSurfaceView;
import com.example.state.Achievement;
import com.example.state.AppState;
import com.example.state.Ball;
import com.example.state.Home;
import com.example.state.InGame;
import com.example.state.World;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;

public class Bounce extends Activity{
    /**
     * The list of state of the game.
     * The list of state is as follow :
     *  - Home
     *  - World
     *  - Ball
     *  - InGame
     *  - Ball
     *  - Achievement
     */
    private List<AppState> _listState;
    /**
     * The current state of the game
     */
    private AppState _currentState;
    /**
     * The GLSurfaceView used to draw each object of the game
     */
    private MyGLSurfaceView _glSurfaceView;
    /**
     * The debug TAG
     */
    private final static String TAG = "Bounce";
    /**
     * The timer handles the frame rate and the calculation of the next frame
     */
    private Timer _gameTimer;
    /**
     * The difficulty of the level represent by a ball
     */
    int _difficulty;
    /**
     * The selected world
     */
    int _world;

    /**
     * call the function onKeyDown of the current state
     * @param keyCode the code of the key
     * @param event the input event of the user
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return _currentState.onKeyDown(keyCode, event);
    }

    /**
     * create the context of the game
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // set the orientation and the parameters of the screen
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        // Check if the system supports OpenGL ES 2.0.
        final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;

        if (supportsEs2)
        {
            // set the value of the application
            _gameTimer = new Timer();
            _glSurfaceView = new MyGLSurfaceView(this);
            setContentView(_glSurfaceView);

            // set the list of state of the game
            _listState = new ArrayList<AppState>();
            _listState.add(new Home(this, _glSurfaceView));
            _listState.add(new Achievement(this, _glSurfaceView));
            _listState.add(new World(this, _glSurfaceView));
            _listState.add(new Ball(this, _glSurfaceView));
            _listState.add(new InGame(this, _glSurfaceView));
            _currentState = _listState.get(AppState.HOME);

            changeState(AppState.HOME);

        }
        else
        {
            // This is where you could create an OpenGL ES 1.x compatible
            // renderer if you wanted to support both ES 1 and ES 2.
            Toast.makeText(this, "Your device doesn't support openGL es 2.0", Toast.LENGTH_LONG);
            finish();
        }
    }

    /**
     * call everytime before exiting the application
     */
    private void beforeFinish(){
        _glSurfaceView.onPause();
        if(_currentState.isRunning()){
            _currentState.cancel();
        }
        _gameTimer.purge();
    }

    /**
     * change the current state of the game
     * @param nextState the next state of the game
     */
    public void changeState(int nextState){
        if(_currentState.isRunning()){
                _currentState.cancel();
                _gameTimer.purge();
            }
            _currentState.clearGameShape();
            switch(nextState){
                case AppState.HOME:
                    _currentState = new Home(this, _glSurfaceView);
                    break;
                case AppState.WORLD:
                    _currentState = new World(this, _glSurfaceView);
                    break;
                case AppState.BALL:
                    _currentState = new Ball(this, _glSurfaceView);
                    break;
                case AppState.ACHIEVEMENT:
                    _currentState = new Achievement(this, _glSurfaceView);
                    break;
                case AppState.INGAME:
                    _currentState = new InGame(this, _glSurfaceView);
                    break;
                case AppState.EXIT:
                    beforeFinish();
                    finish();
                    break;
                default:
                    _currentState = new Home(this, _glSurfaceView);
                    break;
            }

            _currentState.setState(nextState);
            _glSurfaceView.setState(_currentState);
            _currentState.initGameShape();
            _gameTimer.scheduleAtFixedRate(_currentState, 200, 20);
            Log.i(TAG, "new state : " + _currentState.toString());

        }

    /**
     * setter of the difficulty
     * @param difficulty
     */
    public void setDifficulty(int difficulty) {
        _difficulty = difficulty;
    }

    /**
     * setter of the level
     * @param world
     */
    public void setWorld(int world){
        _world = world;
    }

    /**
     * Call when we pause the game.
     * Pause both the GLSurfaceView and the timer
     */
    @Override
    protected void onPause() {
        super.onPause();
        _glSurfaceView.onPause();
        if(_currentState.isRunning()){
            _currentState.cancel();
        }
    }

    /**
     * Resume the state of the game
     */
    @Override
    protected void onResume() {
        super.onResume();
        _glSurfaceView.onResume();
    }

    /**
     * change the view of the Renderer
     * @param delta
     */
    public void changeView(float delta) {
        _glSurfaceView.changeView(delta);
    }

    public int getWorld() {
        return _world;
    }

    public int getDifficulty(){
        return _difficulty;
    }
}
